using BuildingBlocks.Core.Entities;
using Catalog.Domain.Events;
using Catalog.Domain.Exceptions;

namespace Catalog.Domain.Entities;
public class CatalogItem : AggregateRoot<Guid>
{
    public string Name { get; private set; } = null!;
    public string? Description { get; private set; }
    public decimal Price { get; private set; }
    public int AvailableStock { get; private set; }
    public Guid CategoryId { get; private set; }
    public Guid BrandId { get; private set; }

    // 构造函数、行为方法（如：AddStock(), RemoveStock(), ChangePrice()）等
    private CatalogItem() { }

    public static CatalogItem Create(string name, string? description, decimal price, int availableStock, Guid catalogTypeId, Guid catalogBrandId)
    {
        if (string.IsNullOrWhiteSpace(name)) throw new ArgumentException("Name cannot be empty.", nameof(name));
        if (price < 0) throw new ArgumentOutOfRangeException(nameof(price), "Price cannot be negative.");
        if (availableStock < 0) throw new ArgumentOutOfRangeException(nameof(availableStock), "Available stock cannot be negative.");

        return new CatalogItem
        {
            Id = Guid.NewGuid(),
            Name = name,
            Description = description,
            Price = price,
            AvailableStock = availableStock,
            CategoryId = catalogTypeId,
            BrandId = catalogBrandId
        };
    }

    public void UpdateStock(int quantity)
    {
        if (quantity < 0 && Math.Abs(quantity) > AvailableStock)
            throw new InvalidOperationException("Cannot remove more stock than available.");

        AvailableStock += quantity;
        AddDomainEvent(new StockUpdatedDomainEvent(Id, AvailableStock));
    }

    public void ChangeName(string newName)
    {
        if (string.IsNullOrWhiteSpace(newName))
            throw new DomainException("Name cannot be empty.");

        if (Name == newName) return;

        Name = newName;
    }

    public void ChangePrice(decimal newPrice)
    {
        if (newPrice < 0) throw new ArgumentOutOfRangeException(nameof(newPrice), "Price cannot be negative.");

        Price = newPrice;
        AddDomainEvent(new PriceChangedDomainEvent(Id, Price));
    }

    public void ChangeBrand(Guid newBrandid)
    {
        if (BrandId == newBrandid) return;
        BrandId = newBrandid;
    }

    public void ChangeCategory(Guid newCategoryid)
    {
        if (CategoryId == newCategoryid) return;
        CategoryId = newCategoryid;
    }

    public void ChangeDescription(string? newDescription)
    {
        if (Description == newDescription) return;
        Description = newDescription;
    }
}